package jmine.tec.database.query;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

/**
 * Chave exportada, refere-se a uma chave estrangeira que referencia a chave primária da tabela.
 * 
 * @author lundberg
 */
public class ExportedKey {

    private Table referenced;

    private Table referencing;

    private List<ColumnReference> references = new ArrayList<ColumnReference>();

    /**
     * Construtor
     * 
     * @param referenced referenced
     * @param referencing referencing
     */
    public ExportedKey(Table referenced, Table referencing) {
        this.referenced = referenced;
        this.referencing = referencing;
    }

    /**
     * @return the referenced
     */
    public Table getReferenced() {
        return this.referenced;
    }

    /**
     * @return the referencing
     */
    public Table getReferencing() {
        return this.referencing;
    }

    /**
     * @return the references
     */
    public List<ColumnReference> getReferences() {
        return Collections.unmodifiableList(this.references);
    }

    /**
     * Adiciona uma par de colunas que fazem parte da referência
     * 
     * @param referencedColumn referencedColumn
     * @param referencingColumn referencingColumn
     */
    public void addReference(String referencedColumn, String referencingColumn) {
        this.references
                .add(new ColumnReference(this.referenced.getColumn(referencedColumn), this.referencing.getColumn(referencingColumn)));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof ExportedKey)) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        ExportedKey o = (ExportedKey) obj;
        EqualsBuilder builder = new EqualsBuilder();
        builder.append(this.referencing, o.referencing);
        builder.append(this.referenced, o.referenced);
        builder.append(this.references, o.references);
        return builder.isEquals();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(this.referencing).append(this.referenced).append(this.references).toHashCode();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return String.format("ExportedKey:referencing[%s]referenced[%s]references[%s]", this.referencing, this.referenced, this.references);
    }

    /**
     * Referência entre duas colunas via chave estrangeira
     * 
     * @author lundberg
     */
    static final class ColumnReference {
        private final Column referencedColumn;

        private final Column referencingColumn;

        /**
         * Construtor
         * 
         * @param referencedColumn referencedColumn
         * @param referencingColumn referencingColumn
         */
        private ColumnReference(Column referencedColumn, Column referencingColumn) {
            this.referencedColumn = referencedColumn;
            this.referencingColumn = referencingColumn;
        }

        /**
         * @return the referencedColumn
         */
        public Column getReferencedColumn() {
            return this.referencedColumn;
        }

        /**
         * @return the referencingColumn
         */
        public Column getReferencingColumn() {
            return this.referencingColumn;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof ColumnReference)) {
                return false;
            }
            if (this == obj) {
                return true;
            }
            ColumnReference o = (ColumnReference) obj;
            EqualsBuilder builder = new EqualsBuilder();
            builder.append(this.referencedColumn, o.referencedColumn);
            builder.append(this.referencingColumn, o.referencingColumn);
            return builder.isEquals();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public int hashCode() {
            return new HashCodeBuilder().append(this.referencedColumn).append(this.referencingColumn).toHashCode();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public String toString() {
            return String.format("ColumnReference:referencing[%s]referenced[%s]", this.referencingColumn, this.referencedColumn);
        }
    }
}
